home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1996 September / macformat-041.iso / mac / Shareware City / Graphics / MacSPD / Sources / libpr3.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-22  |  11.4 KB  |  433 lines  |  [TEXT/MMCC]

  1. /*
  2.  * libpr3.c - a library of primitive object output routines, part 3 of 3.
  3.  *
  4.  * Author:  Eric Haines, 3D/Eye, Inc.
  5.  *
  6.  */
  7.  
  8. /*-----------------------------------------------------------------*/
  9. /* include section */
  10. /*-----------------------------------------------------------------*/
  11.  
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <math.h>
  15. #include <string.h>
  16.  
  17. #include "lib.h"
  18. #include "drv.h"
  19.  
  20.  
  21. /*-----------------------------------------------------------------*/
  22. /* defines/constants section */
  23. /*-----------------------------------------------------------------*/
  24.  
  25.  
  26. static unsigned int hfcount = 0;
  27.  
  28. /*-----------------------------------------------------------------*/
  29. static char *
  30. create_height_file(filename, height, width, data, type)
  31.     char *filename;
  32.     int height, width;
  33.     float **data;
  34.     int type;
  35. {
  36.     FILE *file;
  37.     float v;
  38.     unsigned int i, j;
  39.     unsigned char r, g, b;
  40.     unsigned char tgaheader[18];
  41.  
  42.     if (filename == NULL) {
  43.     /* Need to create a new name for the height file */
  44.     filename = malloc(10 * sizeof(char));
  45.     if (filename == NULL) return NULL;
  46.     sprintf(filename, "hf%03d.tga", hfcount++);
  47.     }
  48.     if ((file = fopen(filename, "wb")) == NULL) return NULL;
  49.     if (type == 0) {
  50.     /* Targa style height field for POV-Ray or Polyray */
  51.     memset(tgaheader, 0, 18);
  52.     tgaheader[2] = 2;
  53.     tgaheader[12] = (unsigned char)(width & 0xFF);
  54.     tgaheader[13] = (unsigned char)((width >> 8) & 0xFF);
  55.     tgaheader[14] = (unsigned char)(height & 0xFF);
  56.     tgaheader[15] = (unsigned char)((height >> 8) & 0xFF);
  57.     tgaheader[16] = 24;
  58.     tgaheader[17] = 0x20;
  59.     fwrite(tgaheader, 18, 1, file);
  60.     for (i=0;i<height;i++) {
  61.         PLATFORM_MULTITASK();
  62.         for (j=0;j<width;j++) {
  63.         v = data[i][j];
  64.         if (v < -128.0) v = -128.0;
  65.         if (v > 127.0) v = 127.0;
  66.         v += 128.0;
  67.         r = v;
  68.         v -= (float)r;
  69.         g = (unsigned char)(256.0 * v);
  70.         b = 0;
  71.         fputc(b, file);
  72.         fputc(g, file);
  73.         fputc(r, file);
  74.         }
  75.     }
  76.     } else {
  77.     /* Only square height fields in RayShade */
  78.     if (height < width) width = height;
  79.     else if (width < height) height = width;
  80.  
  81.     /* Start by storing the size as an int */
  82.     fwrite(&height, sizeof(int), 1, file);
  83.  
  84.     /* Now store height values as native floats */
  85.     for (i=0;i<height;i++)
  86.         for (j=0;j<width;j++)
  87.         fwrite(&data[i][j], sizeof(float), 1, file);
  88.     }
  89.     fclose(file);
  90.  
  91.     return filename;
  92. }
  93.  
  94.  
  95. /*-----------------------------------------------------------------*/
  96. void
  97. lib_output_height(filename, data, height, width, x0, x1, y0, y1, z0, z1)
  98.     char *filename;
  99.     float **data;
  100.     int height, width;
  101.     double x0, x1;
  102.     double y0, y1;
  103.     double z0, z1;
  104. {
  105.     MATRIX txmat;
  106.     object_ptr new_object;
  107.  
  108.     if (gRT_out_format == OUTPUT_DELAYED) {
  109.     filename = create_height_file(filename, height, width, data, 0);
  110.     if (filename == NULL) return;
  111.  
  112.     /* Save all the pertinent information */
  113.     new_object = (object_ptr)malloc(sizeof(struct object_struct));
  114.     if (new_object == NULL)
  115.         /* Quietly fail */
  116.         return;
  117.     new_object->object_type  = HEIGHT_OBJ;
  118.     new_object->curve_format = OUTPUT_CURVES;
  119.     new_object->surf_index   = gTexture_count;
  120.     if (lib_tx_active()) {
  121.         lib_get_current_tx(txmat);
  122.         new_object->tx = malloc(sizeof(MATRIX));
  123.         if (new_object->tx == NULL)
  124.            return;
  125.         else
  126.            memcpy(new_object->tx, txmat, sizeof(MATRIX));
  127.         }
  128.     else
  129.        new_object->tx = NULL;
  130.     new_object->object_data.height.width = width;
  131.     new_object->object_data.height.height = height;
  132.     new_object->object_data.height.data = data;
  133.     new_object->object_data.height.filename = filename;
  134.     new_object->object_data.height.x0 = x0;
  135.     new_object->object_data.height.x1 = x1;
  136.     new_object->object_data.height.y0 = y0;
  137.     new_object->object_data.height.y1 = y1;
  138.     new_object->object_data.height.z0 = z0;
  139.     new_object->object_data.height.z1 = z1;
  140.     new_object->next_object = gLib_objects;
  141.     gLib_objects = new_object;
  142.     } else {
  143.     switch (gRT_out_format) {
  144.         case OUTPUT_VIDEO:
  145.         case OUTPUT_NFF:
  146.         case OUTPUT_PLG:
  147.         case OUTPUT_OBJ:
  148.         case OUTPUT_QRT:
  149.         case OUTPUT_RTRACE:
  150.         case OUTPUT_VIVID:
  151.         case OUTPUT_RAWTRI:
  152.         case OUTPUT_RIB:
  153.         case OUTPUT_DXF:
  154.         case OUTPUT_RWX:
  155.         lib_output_polygon_height(height, width, data,
  156.                           x0, x1, y0, y1, z0, z1);
  157.         break;
  158.         case OUTPUT_POVRAY_10:
  159.         case OUTPUT_POVRAY_20:
  160.         filename = create_height_file(filename, height, width, data, 0);
  161.         if (filename == NULL) return;
  162.  
  163.         tab_indent();
  164.         fprintf(gOutfile, "object {\n");
  165.         tab_inc();
  166.  
  167.         tab_indent();
  168.         fprintf(gOutfile, "height_field { tga \"%s\" }", filename);
  169.         if (gRT_out_format == OUTPUT_POVRAY_10) {
  170.             tab_indent();
  171.             fprintf(gOutfile, "scale <%g %g %g>\n",
  172.                 fabs(x1 - x0), fabs(y1 - y0), fabs(z1 - z0));
  173.             tab_indent();
  174.             fprintf(gOutfile, "translate <%g %g %g>\n", x0, y0, z0);
  175.         } else {
  176.             tab_indent();
  177.             fprintf(gOutfile, "scale <%g, %g, %g>\n",
  178.                 fabs(x1 - x0), fabs(y1 - y0), fabs(z1 - z0));
  179.             tab_indent();
  180.             fprintf(gOutfile, "translate <%g, %g, %g>\n", x0, y0, z0);
  181.         }
  182.  
  183.         if (lib_tx_active())
  184.            lib_output_tx_sequence();
  185.  
  186.         if (gTexture_name != NULL) {
  187.             tab_indent();
  188.             fprintf(gOutfile, "texture { %s }\n", gTexture_name);
  189.         }
  190.  
  191.         tab_dec();
  192.         tab_indent();
  193.         fprintf(gOutfile, "} // object - Height Field\n");
  194.         fprintf(gOutfile, "\n");
  195.         break;
  196.  
  197.         case OUTPUT_POLYRAY:
  198.         filename = create_height_file(filename, height, width, data, 0);
  199.         if (filename == NULL) return;
  200.         tab_indent();
  201.         fprintf(gOutfile, "object { height_field \"%s\" ", filename);
  202.         fprintf(gOutfile, "scale <%g, 1, %g> ",
  203.             fabs(x1-x0), fabs(z1-z0));
  204.         fprintf(gOutfile, "translate <%g, %g, %g> ", x0, y0, z0);
  205.         if (lib_tx_active())
  206.            lib_output_tx_sequence();
  207.         if (gTexture_name != NULL)
  208.             fprintf(gOutfile, " %s", gTexture_name);
  209.         fprintf(gOutfile, " }\n");
  210.         fprintf(gOutfile, "\n");
  211.         break;
  212.  
  213.         case OUTPUT_RAYSHADE:
  214.         filename = create_height_file(filename, height, width, data, 1);
  215.         if (filename == NULL) return;
  216.         fprintf(gOutfile, "heightfield ");
  217.         if (gTexture_name != NULL)
  218.             fprintf(gOutfile, " %s", gTexture_name);
  219.         fprintf(gOutfile, "\"%s\" ", filename);
  220.         fprintf(gOutfile, "rotate 1 0 0 90 ");
  221.         fprintf(gOutfile, "scale  %g 1 %g ",
  222.             fabs(x1 - x0), fabs(z1 - z0));
  223.         fprintf(gOutfile, "translate  %g %g %g ", x0, y0, z0);
  224.         if (lib_tx_active())
  225.            lib_output_tx_sequence();
  226.         fprintf(gOutfile, "\n");
  227.         break;
  228.  
  229.         case OUTPUT_ART:
  230.         filename = create_height_file(filename, height, width, data, 1);
  231.         if (filename == NULL) return;
  232.  
  233.         tab_indent();
  234.         fprintf(gOutfile, "geometry {\n");
  235.         tab_inc();
  236.  
  237.         if (lib_tx_active())
  238.            lib_output_tx_sequence();
  239.  
  240.         tab_indent();
  241.         fprintf(gOutfile, "translate(%g, %g, %g)\n", x0, y0, z0);
  242.         tab_indent();
  243.         fprintf(gOutfile, "scale(%g, 1, %g)\n",
  244.             fabs(x1 - x0), fabs(z1 - z0));
  245.         tab_indent();
  246.         fprintf(gOutfile, "rotate(-90, x)\n");
  247.         tab_indent();
  248.         fprintf(gOutfile, "heightfield \"%s\"\n ", filename);
  249.  
  250.         tab_dec();
  251.         tab_indent();
  252.         fprintf(gOutfile, "}\n");
  253.         fprintf(gOutfile, "\n");
  254.         break;
  255.     }
  256.     }
  257. }
  258.  
  259.  
  260. /*-----------------------------------------------------------------*/
  261. void
  262. lib_output_torus(center, normal, iradius, oradius, curve_format)
  263.     COORD3 center, normal;
  264.     double iradius, oradius;
  265.     int curve_format;
  266. {
  267.     MATRIX txmat;
  268.     object_ptr new_object;
  269.     double len, xang, zang;
  270.  
  271.     PLATFORM_MULTITASK();
  272.     if (gRT_out_format == OUTPUT_DELAYED) {
  273.     /* Save all the pertinent information */
  274.     new_object = (object_ptr)malloc(sizeof(struct object_struct));
  275.     if (new_object == NULL)
  276.         /* Quietly fail */
  277.         return;
  278.     new_object->object_type  = TORUS_OBJ;
  279.     new_object->curve_format = curve_format;
  280.     new_object->surf_index   = gTexture_count;
  281.     if (lib_tx_active()) {
  282.         lib_get_current_tx(txmat);
  283.         new_object->tx = malloc(sizeof(MATRIX));
  284.         if (new_object->tx == NULL)
  285.            return;
  286.         else
  287.            memcpy(new_object->tx, txmat, sizeof(MATRIX));
  288.         }
  289.     else
  290.        new_object->tx = NULL;
  291.     COPY_COORD3(new_object->object_data.torus.center, center);
  292.     COPY_COORD3(new_object->object_data.torus.normal, normal);
  293.     new_object->object_data.torus.iradius = iradius;
  294.     new_object->object_data.torus.oradius = oradius;
  295.     new_object->next_object = gLib_objects;
  296.     gLib_objects = new_object;
  297.     } else if (curve_format == OUTPUT_CURVES) {
  298.     switch (gRT_out_format) {
  299.         case OUTPUT_VIDEO:
  300.         case OUTPUT_NFF:
  301.         case OUTPUT_VIVID:
  302.         case OUTPUT_QRT:
  303.         case OUTPUT_POVRAY_10:
  304.         case OUTPUT_PLG:
  305.         case OUTPUT_OBJ:
  306.         case OUTPUT_RTRACE:
  307.         case OUTPUT_RAWTRI:
  308.         case OUTPUT_DXF:
  309.         case OUTPUT_RWX:
  310.         lib_output_polygon_torus(center, normal, iradius, oradius);
  311.         break;
  312.         case OUTPUT_POVRAY_20:
  313.         /*
  314.          A torus object lies in the x-z plane.  We need to determine
  315.          the angles of rotation to get it lined up with "normal".
  316.          */
  317.         tab_indent();
  318.         fprintf(gOutfile, "torus {\n");
  319.         tab_inc();
  320.  
  321.         tab_indent();
  322.         fprintf(gOutfile, "%g, %g\n", iradius, oradius);
  323.  
  324.         (void)lib_normalize_vector(normal);
  325.         len = sqrt(normal[X] * normal[X] + normal[Y] * normal[Y]);
  326.         xang = 180.0 * asin(normal[Z]) / PI;
  327.         if (len < EPSILON)
  328.             zang = 0.0;
  329.         else
  330.             zang = -180.0 * acos(normal[Y] / len) / PI;
  331.         if (normal[X] < 0)
  332.             zang = -zang;
  333.  
  334.         if (ABSOLUTE(xang) > EPSILON || ABSOLUTE(zang) > EPSILON) {
  335.             tab_indent();
  336.             fprintf(gOutfile, "rotate <%g, 0, %g>\n", xang, zang);
  337.         }
  338.  
  339.         if (ABSOLUTE(center[X]) > EPSILON ||
  340.             ABSOLUTE(center[Y]) > EPSILON ||
  341.             ABSOLUTE(center[Z]) > EPSILON) {
  342.             tab_indent();
  343.             fprintf(gOutfile, "translate <%g, %g, %g>\n",
  344.                 center[X], center[Y], center[Z]);
  345.         }
  346.         if (lib_tx_active())
  347.            lib_output_tx_sequence();
  348.  
  349.         if (gTexture_name != NULL) {
  350.             tab_indent();
  351.             fprintf(gOutfile, "texture { %s }\n", gTexture_name);
  352.         }
  353.         fprintf(gOutfile, "\n");
  354.  
  355.         tab_dec();
  356.         tab_indent();
  357.         fprintf(gOutfile, "} // torus\n");
  358.         fprintf(gOutfile, "\n");
  359.         break;
  360.  
  361.         case OUTPUT_POLYRAY:
  362.         tab_indent();
  363.         fprintf(gOutfile, "object { torus %g, %g", iradius, oradius);
  364.         fprintf(gOutfile, ", <%g, %g, %g>, <%g, %g, %g>",
  365.             center[X], center[Y], center[Z],
  366.             normal[X], normal[Y], normal[Z]);
  367.         if (lib_tx_active())
  368.            lib_output_tx_sequence();
  369.         if (gTexture_name != NULL)
  370.             fprintf(gOutfile, " %s", gTexture_name);
  371.         fprintf(gOutfile, " }\n");
  372.         fprintf(gOutfile, "\n");
  373.         break;
  374.  
  375.         case OUTPUT_RAYSHADE:
  376.         fprintf(gOutfile, "torus ");
  377.         if (gTexture_name != NULL)
  378.             fprintf(gOutfile, "%s ", gTexture_name);
  379.         fprintf(gOutfile, " %g %g %g %g %g %g %g %g ",
  380.             iradius, oradius,
  381.             center[X], center[Y], center[Z],
  382.             normal[X], normal[Y], normal[Z]);
  383.         if (lib_tx_active())
  384.            lib_output_tx_sequence();
  385.         fprintf(gOutfile, "\n");
  386.  
  387.         break;
  388.  
  389.         case OUTPUT_ART:
  390.         tab_indent();
  391.         fprintf(gOutfile, "torus {\n");
  392.         tab_inc();
  393.  
  394.         if (lib_tx_active())
  395.            lib_output_tx_sequence();
  396.  
  397.         tab_indent();
  398.         fprintf(gOutfile, "center(0, 0, 0)  radius %g radius %g\n",
  399.             iradius, oradius);
  400.  
  401.         (void)lib_normalize_vector(normal);
  402.         axis_to_z(normal, &xang, &zang);
  403.  
  404.         if (ABSOLUTE(xang) > EPSILON) {
  405.             tab_indent();
  406.             fprintf(gOutfile, "rotate (%g, x)\n", xang);
  407.         }
  408.         if (ABSOLUTE(zang) > EPSILON) {
  409.             tab_indent();
  410.             fprintf(gOutfile, "rotate (%g, y)\n", zang);
  411.         }
  412.  
  413.  
  414.         if (ABSOLUTE(center[X]) > EPSILON ||
  415.             ABSOLUTE(center[Y]) > EPSILON ||
  416.             ABSOLUTE(center[Z]) > EPSILON) {
  417.             tab_indent();
  418.             fprintf(gOutfile, "translate (%g, %g, %g)\n",
  419.                 center[X], center[Y], center[Z]);
  420.         }
  421.  
  422.         tab_dec();
  423.         tab_indent();
  424.         fprintf(gOutfile, "}\n");
  425.         fprintf(gOutfile, "\n");
  426.         break;
  427.     }
  428.     } else {
  429.     lib_output_polygon_torus(center, normal, iradius, oradius);
  430.     }
  431. }
  432.  
  433.